#include "data_flood.h"
#include <unistd.h>

typedef struct CopyFileInfo {
    MyThreadHandle *thread_handle;
    volatile int cur_file_no;
    int files;
    char base_file_path[DF_MAX_PATH_LEN];
    char *base_buff;
}CopyFileInfo;

CopyFileInfo cf_info;


static int get_next_file(void)
{
    int new_file_no = 0;

    new_file_no = __sync_add_and_fetch(&cf_info.cur_file_no, 1);

    return new_file_no;
}

static int get_current_file(void)
{
    int new_file_no = 0;

    new_file_no = *(int*)(&cf_info.cur_file_no);

    return new_file_no;
}

void* run_copy_file(void* arg)
{
    MyThreadHandle *cur_thread = NULL;
    int my_file_no = 0;

    cur_thread = (MyThreadHandle*)arg;
    while(true) {
	    my_file_no = get_next_file();
        if(my_file_no >= cf_info.files)
            break;
        copy_1G_file(cf_info.base_file_path, my_file_no, cur_thread);
        df_debug("Thread %d finish %d file; Time Takes(ms) readBuf %lu, hackerBuff %lu, writeBuff %lu, closeFile %lu", 
                    cur_thread->thrd_no, my_file_no, cur_thread->fc_sta.copy_buff_time/1000000, cur_thread->fc_sta.hack_buff_time/1000000,
                    cur_thread->fc_sta.write_buff_time/1000000, cur_thread->fc_sta.close_file_time/1000000);
    }
    if(cur_thread->hack_buff) {
        free(cur_thread->hack_buff);
        cur_thread->hack_buff = NULL;
    }
    cur_thread->finish = true;
}

void run_copyfile_thread(int thrd_num, int files, char* filepath)
{
    int err = 0;
    FILE *fp_source = NULL;
    uint64 read_num = 0;
    
    memset(&cf_info, 0, sizeof(CopyFileInfo));
    cf_info.thread_handle = (MyThreadHandle*)df_malloc(sizeof(MyThreadHandle) * thrd_num);
    memcpy(cf_info.base_file_path, filepath, strlen(filepath));
    cf_info.files = files;

    cf_info.base_buff = df_malloc(BYTES_IN_1G);
    fp_source = fopen(filepath, "r");
	if(!fp_source)
		df_error("Can not open file %s to read:%m", filepath);
    read_num = fread(cf_info.base_buff, 1, BYTES_IN_1G, fp_source);
    if(BYTES_IN_1G != read_num)
        df_error("Read file %s except %lu but %lu", BYTES_IN_1G, read_num);
    fclose(fp_source);
    fp_source = NULL;

    for(int loop = 0; loop < thrd_num; loop++) {
        MyThreadHandle *cur_thrd= &cf_info.thread_handle[loop];

        cur_thrd->base_buff = cf_info.base_buff;
        err = pthread_create(&cur_thrd->thread_ptr, NULL, run_copy_file, cur_thrd);
        cur_thrd->thrd_no = loop;

        if (err != 0 || cur_thrd->thread_ptr == 0)
            df_error("cannot create thread: %s\n", strerror(err));
    }

    while(true) {
        int finish_num = 0;

        for(int loop = 0; loop < thrd_num; loop++) {
            if(cf_info.thread_handle[loop].finish)
                finish_num++;
        }
        ratio_print("Flood Ratio", get_current_file(), files, false);
        usleep(1000000);
        if(finish_num >= thrd_num)
            break;
    }
    ratio_print("Flood Ratio", get_current_file(), files, true);
    df_debug("Copy Finish");

}